package main

import (
	"bufio"
	"config-client-v1/utils/tools"
	"flag"
	"fmt"
	"golang.org/x/net/context"
	"io"
	"net"
	"strings"
	"time"
)

const BYTE_LENGTH = 4096

type Client struct {
	RemoteAddr   string // 客户端 IP + 端口
	Connection   net.Conn
	Reader       *bufio.Reader
	CreateTime   time.Time // 连接时间
	LastDataTime time.Time // 最近一次接收数据的时间
}

var C1 *Client

var addr string

func main() {
	addrP := flag.String("addr", "192.168.1.179:4001", "tcp服务端地址")
	flag.Parse()
	addr = *addrP
	C1 = &Client{}
	connectServer()
}

func connectServer() {
	fmt.Println("正在连接 周立功CAN2.0-TCP Server", addr)
	conn, err0 := net.Dial("tcp", addr)
	if err0 != nil {
		errorHandle(err0, 1)
		return
	}
	defer func() {
		_ = conn.Close()
	}()
	C1.Connection = conn
	fmt.Println("server连接成功")
	C1.Reader = bufio.NewReader(C1.Connection) // 创建一个tcp返回 reader
	// 心跳检测
	ctx, cancelHeartBeat := context.WithCancel(context.Background())
	go heartBeatCheck(ctx)
	//go func() {
	//	time.Sleep(10 * time.Second)
	//	err := C1.Connection.Close()
	//	fmt.Printf("关闭socket连接查看一下 netstat -ano | findstr :9528 LISTENING 状态 %v\n", err)
	//}()
	var buffer [BYTE_LENGTH]byte
	for {
		n, err := C1.Reader.Read(buffer[0:])
		if err != nil {
			if err == io.EOF {
				fmt.Println("io.EOF error", err)
				//continue
			}
			if err == net.ErrClosed || strings.Contains(err.Error(), "use of closed network connection") || strings.Contains(err.Error(), "read: connection reset by peer") || strings.Contains(err.Error(), "closed by the remote host") {
				fmt.Println("PING error")
			} else {
				fmt.Println("unknown read error: ", err)
			}
			cancelHeartBeat()
			reconnect()
			return
		}
		//fmt.Println(buffer[0:n])
		str := tools.ByteArrayToHexStr(buffer[0:n])
		fmt.Printf("[%s~%s] len=%d : %s\n", tools.GetNow(), C1.RemoteAddr, n, str)
		// 清空buffer
		for i := 0; i < n; i++ {
			buffer[i] = 0
		}
	}
}

func heartBeatCheck(ctx context.Context) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("heartbeat panic: ", err)
		}
	}()
	var counter uint16
	counter = 1
	for {
		select {
		case <-ctx.Done():
			fmt.Println("=== 取消了heartBeat协程 ===")
			return
		default:
			//idxByte := tools.Uint16ToBytes(counter, "big")
			//idxStr := tools.ByteArrayToHexStr(idxByte[0:2])
			//message := idxStr + "000000060101000A0011"
			//fmt.Printf("message=%s\n", message)
			//b, err := tools.HexStrToByteArray(message)
			//if err != nil {
			//	fmt.Printf("error HexStrToByteArray=%v\n", err.Error())
			//	return
			//}
			//b := []byte{0x5A, 0x01, 0x01, 0x00, 0x0C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xA5}
			//n, err := C1.Connection.Write(b)
			//fmt.Printf("n=%d err=%v\n", n, err)
			counter++
			time.Sleep(1 * time.Second)
		}
	}
}

func writeByte(b []byte) error {
	_, _ = C1.Connection.Write(b)
	return nil
}

func errorHandle(err error, rec int8) {
	if err == io.EOF {
		fmt.Println("远程连接已关闭.")
	} else if strings.Contains(err.Error(), "No connection could be made because the target machine actively refused it") {
		fmt.Println("server连接失败, 目标计算机积极拒绝")
	} else if strings.Contains(err.Error(), "was forcibly closed by the remote host") {
		fmt.Println("远程连接已关闭..")
	} else if err == net.ErrClosed || strings.Contains(err.Error(), "use of closed network connection") || strings.Contains(err.Error(), "read: connection reset by peer") || strings.Contains(err.Error(), "closed by the remote host") {
		fmt.Println("连接已关闭或重置")
	} else {
		fmt.Println("连接服务端失败: ", err)
	}
	if rec == 1 {
		//reconnect()
	}
}

func reconnect() {
	//return
	fmt.Println("3秒后重试")
	time.Sleep(3 * time.Second)
	connectServer()
}
